#pragma once
#include <iostream>
#include <functional>
#include "sock.hpp"
#include <pthread.h>
#include "protocol.hpp"

using namespace std;
using namespace protocol_ns;

namespace tcpserver_ns{

    class TcpServer;

    using func_t = function<Response(const Request &)>;

    class ThreadData{
    public:
        ThreadData(int sock,string ip,uint16_t port, TcpServer *p): _sock(sock), _ip(ip), _port(port), _tsvrp(p) {

        }
        ~ThreadData(){
            
        }


    public:
        int _sock;
        string _ip;
        uint16_t _port;
        TcpServer *_tsvrp;
    };

    class TcpServer{
    public:
        TcpServer(func_t func, uint16_t port): _func(func), _port(port){

        }

        ~TcpServer(){
            _listensock.Close();
        }

        //1、初始化服务器
        void InitServer(){
            
            _listensock.Socket();
            _listensock.Bind(_port);
            _listensock.Listen();
            logMessage(INFO, "init server success, listensock: %d", _listensock.Fd());
        }

        static void* ThreadRoutine(void* args){
            pthread_detach(pthread_self());
            ThreadData *td = static_cast<ThreadData *>(args);
            td->_tsvrp->ServiceIO(td->_sock,td->_ip, td->_port);
            logMessage(DEBUG, "thread quit, client  quit!");
            delete td;
            return nullptr;
        }

        //ThreadRountine执行的操作，是被多线程调用的
        void ServiceIO(int sock,const string& ip,const uint16_t &port){
            //用来存放不完整的报文
            string inbuf;
            while(1){
                //1、读read/recv，保证用户获得一个独立的、完整的报文
                // string str;
                // char buf[1024];
                // //不能保证读到的数据是一个独立的、完整的报文（tcp中可能挤压了多个报文，或报文被拆分了只读到一部分）
                // //所以要进行循环，边读取边检测
                // // read(sock, buf, sizeof(buf));
                // ssize_t s = recv(sock, buf, sizeof(buf - 1), 0);
                string package;
                //从客户端读数据到inbuf，当检测到inbuf中存在一个完整的报文的时候，其提取出这个报文，放到package中
                int n = ReadPackage(sock, inbuf, &package);
                if (n == -1){
                    break;
                }else if(n == 0){
                    continue;
                }else{
                    // 2、提取出有效载荷
                    package = RemoveHeader(package, n);

                    // 3、反序列化
                    Request req;
                    req.DesSerialize(package);

                    //4、提取用户的请求数据
                    Response res = _func(req);  //业务逻辑
                    
                    //给用户返回相应
                    //5、 序列化
                    string send_str;
                    res.Serialize(&send_str);

                    //6、添加报头
                    send_str = AddHeader(send_str);
                    
                    //7、发送数据write/send
                    send(sock, send_str.c_str(), send_str.size(), 0);
                }
            }

            close(sock);
        }

        //开始运行
        void Start(){
            while(1){
                string clientip;
                uint16_t clientport;
                int sock = _listensock.Accept(&clientip, &clientport);
                if (sock < 0){
                    continue;
                }
                logMessage(DEBUG, "get a client, client info %s:%d", clientip.c_str(), clientport);

                pthread_t tid;
                ThreadData *td = new ThreadData(sock, clientip, clientport, this);
                pthread_create(&tid, nullptr, ThreadRoutine, td);
            }
        }

    private:
        uint16_t _port;
        Sock _listensock;
        func_t _func;
    };
}